#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <string.h>
#include "shmem.h"
#include "cJSON.h"
#include "msg_queue_peer.h"
#define N 32
#define SHM_SIZE 4096 // 共享内存大小
typedef union
{
    int b_val;   // 布尔型
    int i_val;   // 整型
    float f_val; // 浮点型
} val_t;

// 共享内存节点结构
typedef struct
{
    int key;       // 节点唯一标识
    int type;      // 数据类型 (1:bool, 2:int, 3:float)
    int dev_type;  // 设备类型
    val_t old_val; // 旧值
    val_t new_val; // 新值
    int ret;       // 状态码
} std_node;

static struct shm_param para; // 共享内存所需
static int *total;            // 指向共享内存中数据节点总个数
static std_node *node_arr;    // 指向共享内存中节点缓存数组头
static int stmsize;           // 点表中stm32的节点数量

// 消息队列结构体
//  控制消息结构体
typedef struct
{
    long mtype;  // 控制的设备modbus=1,stm32=2
    int key;     // 要控制的设备key
    val_t value; // 要设置的值
    int type;    // 消息类型
} control_msg;

pthread_t tidA, tidB;
char buffer_data[1024] = {0};
int shmid, msgid;
int ret;
void *preath_processR(void *arg)
{
    // 获取客户端连接套接字作为参数
    int acceptfd = *(int *)arg;
    FILE *file = fopen("data.json", "r");
    if (file == NULL)
    {
        perror("fopen err\n");
        return NULL;
    }

    char configbuf[N * N * 2] = {0};
    size_t len = fread(configbuf, sizeof(char), N * N * 2, file);
    fclose(file); // 添加文件关闭，防止资源泄漏
    if (len <= 0) // 修改判断条件，len=0也是错误
    {
        printf("fread err\n");
        return NULL;
    }

    // 把传入的字符串转成cJSON的结构
    cJSON *root = cJSON_Parse(configbuf);
    if (root == NULL)
    {
        printf("cJSON_Parse err\n");
        return NULL;
    }

    // 获取共享内存中结构体节点数量
    cJSON *stm32 = cJSON_GetObjectItem(root, "stm32");
    if (stm32 == NULL)
    {
        printf("findstm32 err\n");
        cJSON_Delete(root); // 释放JSON内存
        return NULL;
    }

    cJSON *modbus = cJSON_GetObjectItem(root, "modbus");
    if (modbus == NULL)
    {
        printf("findmodbus err\n");
        cJSON_Delete(root); // 释放JSON内存
        return NULL;
    }

    cJSON *stmdata = cJSON_GetObjectItem(stm32, "data");
    if (stmdata == NULL)
    {
        printf("findstmdata err\n");
        cJSON_Delete(root); // 释放JSON内存
        return NULL;
    }

    cJSON *modbusdata = cJSON_GetObjectItem(modbus, "data");
    if (modbusdata == NULL)
    {
        printf("findmodbusdata err\n");
        cJSON_Delete(root); // 释放JSON内存
        return NULL;
    }

    stmsize = cJSON_GetArraySize(stmdata);
    int modbussize = cJSON_GetArraySize(modbusdata);
    printf("std_node_num = %d\n", stmsize + modbussize);

    // 初始化共享内存
    int shmret = -1;
    shmret = shm_init(&para, "shm_test", SHM_SIZE);
    if (shmret < 0)
    {
        //cJSON_Delete(root); // 释放JSON内存
        return NULL;
    }

    void *node_p = shm_getaddr(&para);
    if (node_p == NULL)
    {
        printf("shm_getaddr err\n");
        //cJSON_Delete(root); // 释放JSON内存
        return NULL;
    }

    memset(node_p, 0, SHM_SIZE);
    total = (int *)node_p; // 指向共享内存头
    *total = stmsize + modbussize;
    node_arr = (std_node *)(node_p + sizeof(int)); // 指向共享内存结构体数组头

    // 向共享内存映射结构体节点数据
    for (int i = 0; i < *total; ++i)
    {
        if (i < stmsize)
        {
            cJSON *stmdata_i = cJSON_GetArrayItem(stmdata, i);
            if (!stmdata_i)
                continue;

            cJSON *key = cJSON_GetObjectItem(stmdata_i, "key");
            cJSON *type = cJSON_GetObjectItem(stmdata_i, "type");
            if (key && type)
            {
                node_arr[i].key = key->valueint;
                node_arr[i].type = type->valueint;
                node_arr[i].dev_type = 0;
                node_arr[i].ret = 0;
            }
        }
        else
        {
            cJSON *modbusdata_i = cJSON_GetArrayItem(modbusdata, i - stmsize);
            if (!modbusdata_i)
                continue;

            cJSON *key = cJSON_GetObjectItem(modbusdata_i, "key");
            cJSON *type = cJSON_GetObjectItem(modbusdata_i, "type");
            if (type)
            {
                node_arr[i].type = type->valueint;
                node_arr[i].dev_type = 1;
                node_arr[i].ret = 0;
                if (key)
                {
                    node_arr[i].key = key->valueint;
                }
            }
        }
    }

    cJSON_Delete(root); // 初始配置JSON不再需要，可以释放

    while (1)
    {
        // 从客户端接收数据
        memset(buffer_data, 0, sizeof(buffer_data));
        ret = recv(acceptfd, buffer_data, sizeof(buffer_data) - 1, 0);

        if (ret <= 0)
        {
            if (ret == 0)
            {
                printf("Client disconnected\n");
            }
            else
            {
                perror("recv error");
            }
            break;
        }

        printf("Received from client: %s\n", buffer_data);

        // 1. 解析 JSON
        cJSON *root = cJSON_Parse(buffer_data);
        if (!root)
        {
            printf("JSON 解析失败！\n");
            continue; // 继续处理下一条消息而不是返回
        }

        // 2. 获取 data 数组
        cJSON *data_array = cJSON_GetObjectItem(root, "data");
        if (!data_array)
        {
            printf("No data array found\n");
            cJSON_Delete(root);
            continue;
        }

        // 3. 遍历数组
        int array_size = cJSON_GetArraySize(data_array);
        for (int i = 0; i < array_size && i < *total; i++)
        {
            cJSON *tmp = cJSON_GetArrayItem(data_array, i);

            cJSON *item = cJSON_GetObjectItem(tmp, "key");
            printf("%s=%d\n", item->string, item->valueint);
            int key = item->valueint;
            for (int i = 0; i < 21; i++)
            {
                if (node_arr[i].key == key)
                {
                    // item = cJSON_GetObjectItem(tmp, "val");
                    // printf("%s=%d\n",item->string,item->valueint);
                    cJSON *val_item = cJSON_GetObjectItem(tmp, "val");
                    if (val_item)
                    {
                        printf("%s=", val_item->string);

                        // 判断是整数还是浮点数
                        if (val_item->valuedouble == (int)val_item->valuedouble)
                        {
                            printf("%d\n", (int)val_item->valuedouble); // 整数
                            int val = (int)val_item->valuedouble;
                            node_arr[i].old_val = node_arr[i].new_val;
                            node_arr[i].new_val.i_val = val;
                            printf("更新key=%d的new_val值为%d\n", key, node_arr[i].new_val.i_val);
                        }
                        else
                        {
                            printf("%.2f\n", val_item->valuedouble); // 浮点数
                            double val = val_item->valuedouble;
                            node_arr[i].old_val = node_arr[i].new_val;
                            node_arr[i].new_val.f_val = val;
                            printf("更新key=%d的new_val值为%.2f\n", key, node_arr[i].new_val.f_val);
                        }
                    }
                }
            }
        }
        // 释放JSON内存
        cJSON_Delete(root);
    }
    // 关闭客户端连接
    close(acceptfd);

    pthread_exit(NULL);
}
void *preath_processW(void *arg)
{
    int acceptfd = *(int *)arg;
    char msg[128] = {0};
    char buf[128] = {0};
    control_msg msg_recv;
    int rc;

    // 消息处理循环
    while (1)
    {
        // 清空缓冲区
        memset(&msg_recv, 0, sizeof(msg_recv));
        memset(buf, 0, sizeof(buf));

        // 接收消息队列中的消息
        rc = msg_queue_recv("device_control", &msg_recv, sizeof(msg_recv), 0, 0);
        if (rc < 0) {
            perror("消息队列接收失败");
            sleep(1);
            continue;
        }

        printf("接收到的控制命令类型: %ld, key: %d\n", msg_recv.mtype, msg_recv.key);

        // 处理类型2的消息（控制指令）
        if (msg_recv.mtype == 2)
        {
            if (msg_recv.key == 13)
            {
                if (msg_recv.value.b_val == 1)
                {
                    strncpy(buf, "FAN_ON", sizeof(buf)-1);
                }
                else
                {
                    strncpy(buf, "FAN_OFF", sizeof(buf)-1);
                }
            }
            else if (msg_recv.key == 11)
            {
                if (msg_recv.value.b_val == 1)
                {
                    strncpy(buf, "LED3_ON", sizeof(buf)-1);
                }
                else
                {
                    strncpy(buf, "LED3_OFF", sizeof(buf)-1);
                }
            }

            // 发送响应给客户端
            if (send(acceptfd, buf, strlen(buf), 0) < 0)
            {
                perror("send 错误");
                // 发送失败，退出线程
                break;
            }
            else
            {
                printf("已发送控制响应: %s\n", buf);
            }
        }
    }

    pthread_exit(NULL);
}
int main(int argc, char const *argv[])
{

    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    // 2.填充结构体
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(7776);
    saddr.sin_addr.s_addr = inet_addr("192.168.0.139");

    socklen_t len = sizeof(caddr);

    // 3.绑定信息
    int ret = bind(sockfd, (struct sockaddr *)&saddr, len);
    if (ret < 0)
    {
        perror("bind err");
        return -1;
    }
    // 4.监听
    if (listen(sockfd, 5) < 0)
    {
        perror("listen err");
        return -1;
    }

    // 循环服务器
    while (1)
    {
        // 5.等待连接
        int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
        if (acceptfd < 0)
        {
            perror("accept err");
            return -1;
        }
        printf("accept ok\n");
        // 打印来自客户端的ip地址和端口号
        printf("client ip : %s  port:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
        // 创建线程
        pthread_create(&tidA, NULL, preath_processR, &acceptfd);
        pthread_create(&tidB, NULL, preath_processW, &acceptfd);
        while (1)
        {
        }
        // 8.关闭
        pthread_detach(tidA);
        close(acceptfd);
    }
    close(sockfd);

    return 0;
}
